#include "plugin_outline.h"
#include "ui_plugin_outline.h"
#include "NddPluginBridge.h"
#include <qsciscintilla.h>
#include <Scintilla.h>
#include <QDebug.h>
#include <QDir>
#include <QFileInfo>
#include <QLibrary>

#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"userenv.lib")
#pragma comment(lib,"Ntdll.lib")


typedef int32_t (*ffi_outline_reflash_t) (const char* p_code, uint32_t code_size, const char* p_ext, uint32_t ext_size);
typedef int32_t (*ffi_outline_callback_t) (const char* p_name, int start_pos);
typedef int32_t (*ffi_outline_init_t) (ffi_outline_callback_t);


ffi_outline_reflash_t g_pfn_outline_reflash = nullptr;

PluginOutline::PluginOutline(QWidget *parent, const QString& plgPath)
    : QWidget(parent), ui(new Ui::PluginOutline)
{
    m_plgPath = plgPath;
    g_pfn_outline_reflash = nullptr;

    ui->setupUi(this);
    //ui->outlineTreeView->setMouseTracking(true);
    ui->outlineTreeView->setIndentation(12);
    ui->outlineTreeView->header()->hide();

    m_model = new QStandardItemModel(this);
    ui->outlineTreeView->setModel(m_model);
}

PluginOutline::~PluginOutline()
{
    delete ui;
}

void PluginOutline::set_outline_item(const char *p_name, int32_t start_pos)
{
    if(p_name == nullptr) {
        return;
    }

    QString name = QString::fromUtf8(p_name);

    if (start_pos < 0)
    {
        m_model->clear();
    }

    if (m_model->item(0) == nullptr)
    {
        QStandardItem *item = new QStandardItem(name);
        item->setEditable(false);
        m_model->setItem(0, item);
    }
    else
    {
        QStandardItem *item = new QStandardItem(QIcon(":/img/img/funcList_leaf.png"), name);
        item->setData(start_pos);
        item->setEditable(false);
        int next_row = m_model->item(0)->rowCount();
        m_model->item(0)->setChild(next_row, item);
    }
}

extern NddPluginBridge *pBridge;
extern std::function<QsciScintilla *(QWidget *)> s_getCurEdit;
void PluginOutline::on_outlineTreeView_clicked(const QModelIndex &index)
{
    QStandardItem *item = m_model->itemFromIndex(index);
    // QString name = item->text();
    int start_pos = item->data().value<int>();

    if (pBridge == nullptr)
    {
        return;
    }
    QsciScintilla *hCurrScintilla = s_getCurEdit(pBridge->m_pNotepad);
    if (hCurrScintilla == nullptr)
    {
        return;
    }

    hCurrScintilla->SendScintilla(SCI_GOTOPOS, (long)start_pos);
}

void PluginOutline::reflash_outline()
{
    if(pBridge == nullptr) {
        return;
    }

    QsciScintilla* hCurrScintilla = s_getCurEdit(pBridge->m_pNotepad);
    if (hCurrScintilla == nullptr) {
        return;
    }

    QString text = hCurrScintilla->text();
    QByteArray code = text.toUtf8();

    QString filePath = hCurrScintilla->property("filePath").toString();

    QFileInfo fi(filePath);
    if(fi.exists()) {
        QByteArray suffix = fi.suffix().toUtf8();

        if(g_pfn_outline_reflash == nullptr) {
            load_dll();
        }
        if(g_pfn_outline_reflash) {
            g_pfn_outline_reflash(code.constData(), code.count(), suffix.constData(), suffix.count());
        }

        ui->outlineTreeView->expandAll();
    } else {
        set_outline_item("Unknow file type", -1);
    }

    return;
}

void PluginOutline::load_dll(void)
{
    QDir plgDir = QFileInfo(m_plgPath).absoluteDir();
    QString strName;
    QDir dir = plgDir;
    dir.cd("hell_plugin");

    strName = dir.absolutePath();
    strName += QDir::separator();

#if  defined(Q_OS_WIN)
    strName += "hell_outline_rs.dll";
#else
    strName += "libhell_outline_rs.so";
#endif
    qDebug() << "strName:" << strName;
    QLibrary lib(strName);

    ffi_outline_init_t pfn_outline_init = (ffi_outline_init_t)lib.resolve("ffi_outline_init");
    if(pfn_outline_init) {
        extern int32_t ffi_set_outline_item (const char* p_name, int start_pos);

        int ret = pfn_outline_init(ffi_set_outline_item);
        qDebug() << "pfn_outline_init:" << ret;
        if(ret == 0) {
            qDebug() << "pfn_outline_init: OK";
            g_pfn_outline_reflash = (ffi_outline_reflash_t)lib.resolve("ffi_outline_reflash");
            if(g_pfn_outline_reflash) {
                qDebug() << "g_pfn_outline_reflash: OK";
            }
        }
    }
}

